package com.ruoyi.app.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.ruoyi.app.domain.bo.AppTeamApplyBo;
import com.ruoyi.app.domain.vo.AppTeamApplyVo;
import com.ruoyi.app.service.*;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.constant.TaskConstants;
import com.ruoyi.common.enums.BillType;
import com.ruoyi.common.enums.CoinType;
import com.ruoyi.common.enums.DetailType;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.domain.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruoyi.common.utils.redis.RedisUtils;
import lombok.RequiredArgsConstructor;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import com.ruoyi.app.domain.bo.AppTaskBo;
import com.ruoyi.app.domain.vo.AppTaskVo;
import com.ruoyi.app.domain.AppTask;
import com.ruoyi.app.mapper.AppTaskMapper;

import java.math.BigDecimal;
import java.time.Duration;
import java.util.List;
import java.util.Map;
import java.util.Collection;

/**
 * APP任务记录Service业务层处理
 *
 * @author heike
 * @date 2023-08-28
 */
@RequiredArgsConstructor
@Service
public class AppTaskServiceImpl implements IAppTaskService {

    private final AppTaskMapper baseMapper;
    private final IAppAssetService appAssetService;
    private final IAppDetailService appDetailService;
    private final IAppTeamApplyService appTeamApplyService;

    /**
     * 查询APP任务记录
     */
    @Override
    public AppTaskVo queryById(Long id) {
        return baseMapper.selectVoById(id);
    }

    @Override
    public AppTaskVo queryByName(String name) {
        LambdaQueryWrapper<AppTask> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(AppTask::getKeyName, name);
        return baseMapper.selectVoOne(wrapper);
    }

    @Async
    @Override
    public void downTask(Long id, String name, Long userId) {
        switch (name) {
            case TaskConstants.userLike:
                //右滑喜欢
                String userLikeKey = TaskConstants.userLikeKey + userId;
                Integer userLikeCount = RedisUtils.getCacheObject(userLikeKey);
                if (userLikeCount == null) {
                    userLikeCount = 0;
                }
                if (userLikeCount < TaskConstants.userLikeNumber) {
                    AppTaskVo likeVo = queryByName(TaskConstants.userLike);
                    BigDecimal likeAmount = new BigDecimal(likeVo.getNumber());
                    appAssetService.addIntegral(userId, likeAmount);
                    appDetailService.insert(userId, likeAmount, null, BillType.IN.getCode(), CoinType.INTE.getCode(), DetailType.SCORE.getCode(), TaskConstants.userLike, null);
                    RedisUtils.setCacheObject(userLikeKey, ++userLikeCount, Duration.ofSeconds(DateUtils.seconds()));
                }
                break;
            case TaskConstants.userCert:
                //实名认证
                AppTaskVo userCertVo = queryByName(TaskConstants.userCert);
                BigDecimal userCertAmount = new BigDecimal(userCertVo.getNumber());
                appAssetService.addIntegral(userId, userCertAmount);
                appDetailService.insert(userId, userCertAmount, null, BillType.IN.getCode(), CoinType.INTE.getCode(), DetailType.SCORE.getCode(), TaskConstants.userCert, null);
                break;
            case TaskConstants.invite:
                //邀请用户
                AppTaskVo inviteVo = queryByName(TaskConstants.invite);
                BigDecimal inviteAmount = new BigDecimal(inviteVo.getNumber());
                appAssetService.addIntegral(userId, inviteAmount);
                appDetailService.insert(userId, inviteAmount, null, BillType.IN.getCode(), CoinType.INTE.getCode(), DetailType.SCORE.getCode(), TaskConstants.invite, null);
                break;
            case TaskConstants.userPhrases:
                //打招呼
                String userPhrasesKey = TaskConstants.userPhrasesKey + userId;
                Integer userPhrasesCount = RedisUtils.getCacheObject(userPhrasesKey);
                if (userPhrasesCount == null) {
                    userPhrasesCount = 0;
                }
                if (userPhrasesCount < TaskConstants.userPhrasesNumber) {
                    AppTaskVo taskVo = queryByName(TaskConstants.userPhrases);
                    BigDecimal amount = new BigDecimal(taskVo.getNumber());
                    appAssetService.addIntegral(userId, amount);
                    appDetailService.insert(userId, amount, null, BillType.IN.getCode(), CoinType.INTE.getCode(), DetailType.SCORE.getCode(), TaskConstants.userPhrases, null);
                    RedisUtils.setCacheObject(userPhrasesKey, ++userPhrasesCount, Duration.ofSeconds(DateUtils.seconds()));
                }
                break;
            case TaskConstants.userMate:
                //扫码匹配
                String userMateKey = TaskConstants.userMateKey + userId;
                Integer userMateCount = RedisUtils.getCacheObject(userMateKey);
                if (userMateCount == null) {
                    userMateCount = 0;
                }
                if (userMateCount < TaskConstants.userMateNumber) {
                    AppTaskVo taskVo = queryByName(TaskConstants.userMate);
                    BigDecimal amount = new BigDecimal(taskVo.getNumber());
                    appAssetService.addIntegral(userId, amount);
                    appDetailService.insert(userId, amount, null, BillType.IN.getCode(), CoinType.INTE.getCode(), DetailType.SCORE.getCode(), TaskConstants.userMateKey, null);
                    RedisUtils.setCacheObject(userMateKey, ++userMateCount, Duration.ofSeconds(DateUtils.seconds()));
                }
                break;
            case TaskConstants.createDynamic:
                //发布动态
                String createDynamicKey = TaskConstants.createDynamicKey + userId;
                Integer createDynamicCount = RedisUtils.getCacheObject(createDynamicKey);
                if (createDynamicCount == null) {
                    createDynamicCount = 0;
                }
                if (createDynamicCount < TaskConstants.createDynamicNumber) {
                    AppTaskVo taskVo = queryByName(TaskConstants.createDynamic);
                    BigDecimal amount = new BigDecimal(taskVo.getNumber());
                    appAssetService.addIntegral(userId, amount);
                    appDetailService.insert(userId, amount, null, BillType.IN.getCode(), CoinType.INTE.getCode(), DetailType.SCORE.getCode(), TaskConstants.createDynamic, null);
                    RedisUtils.setCacheObject(createDynamicKey, ++createDynamicCount, Duration.ofSeconds(DateUtils.seconds()));
                }
                break;
            case TaskConstants.teamLike:
                //点赞
                String teamLikeKey = TaskConstants.teamLikeKey + userId;
                Integer teamLikeCount = RedisUtils.getCacheObject(teamLikeKey);
                if (teamLikeCount == null) {
                    teamLikeCount = 0;
                }
                if (teamLikeCount < TaskConstants.teamLikeNumber) {
                    AppTaskVo taskVo = queryByName(TaskConstants.teamLike);
                    BigDecimal amount = new BigDecimal(taskVo.getNumber());
                    appAssetService.addIntegral(userId, amount);
                    appDetailService.insert(userId, amount, null, BillType.IN.getCode(), CoinType.INTE.getCode(), DetailType.SCORE.getCode(), TaskConstants.teamLike, null);
                    RedisUtils.setCacheObject(teamLikeKey, ++teamLikeCount, Duration.ofSeconds(DateUtils.seconds()));
                }
                break;
            case TaskConstants.teamComment:
                //评论
                String key = TaskConstants.teamCommentKey + userId;
                Integer count = RedisUtils.getCacheObject(key);
                if (count == null) {
                    count = 0;
                }
                if (count < TaskConstants.teamCommentNumber) {
                    AppTaskVo taskVo = queryByName(TaskConstants.teamComment);
                    BigDecimal amount = new BigDecimal(taskVo.getNumber());
                    appAssetService.addIntegral(userId, amount);
                    appDetailService.insert(userId, amount, null, BillType.IN.getCode(), CoinType.INTE.getCode(), DetailType.SCORE.getCode(), TaskConstants.teamComment, null);
                    RedisUtils.setCacheObject(key, ++count, Duration.ofSeconds(DateUtils.seconds()));
                }
                break;
            case TaskConstants.complete:
                //判断任务是否有人参加
                AppTeamApplyBo teamApplyBo = new AppTeamApplyBo();
                teamApplyBo.setTeamId(id);
                teamApplyBo.setStatus(Constants.FAIL);
                List<AppTeamApplyVo> teamApplyVos = appTeamApplyService.queryList(teamApplyBo);
                if (teamApplyVos.isEmpty()) {
                    //未完成任务
                    AppTaskVo appTaskVo = queryByName(TaskConstants.incomplete);
                    BigDecimal amount = new BigDecimal(appTaskVo.getNumber());
                    appAssetService.subtractIntegral(userId, amount);
                    appDetailService.insert(userId, amount, null, BillType.TO.getCode(), CoinType.INTE.getCode(), DetailType.SCORE.getCode(), TaskConstants.incomplete, null);
                } else {
                    //完成任务
                    AppTaskVo appTaskVo = queryByName(TaskConstants.complete);
                    BigDecimal amount = new BigDecimal(appTaskVo.getNumber());
                    appAssetService.addIntegral(userId, amount);
                    appDetailService.insert(userId, amount, null, BillType.IN.getCode(), CoinType.INTE.getCode(), DetailType.SCORE.getCode(), TaskConstants.complete, null);
                }
                break;
        }
    }

    /**
     * 查询APP任务记录列表
     */
    @Override
    public TableDataInfo<AppTaskVo> queryPageList(AppTaskBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<AppTask> lqw = buildQueryWrapper(bo);
        Page<AppTaskVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询APP任务记录列表
     */
    @Override
    public List<AppTaskVo> queryList(AppTaskBo bo) {
        LambdaQueryWrapper<AppTask> lqw = buildQueryWrapper(bo);
        lqw.orderByDesc(AppTask::getSort);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<AppTask> buildQueryWrapper(AppTaskBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<AppTask> lqw = Wrappers.lambdaQuery();
        lqw.like(StringUtils.isNotBlank(bo.getName()), AppTask::getName, bo.getName());
        lqw.like(StringUtils.isNotBlank(bo.getKeyName()), AppTask::getKeyName, bo.getKeyName());
        lqw.like(StringUtils.isNotBlank(bo.getType()), AppTask::getType, bo.getType());
        lqw.eq(StringUtils.isNotBlank(bo.getStatus()), AppTask::getStatus, bo.getStatus());
        return lqw;
    }

    /**
     * 新增APP任务记录
     */
    @Override
    public Boolean insertByBo(AppTaskBo bo) {
        AppTask add = BeanUtil.toBean(bo, AppTask.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
        }
        return flag;
    }

    /**
     * 修改APP任务记录
     */
    @Override
    public Boolean updateByBo(AppTaskBo bo) {
        AppTask update = BeanUtil.toBean(bo, AppTask.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(AppTask entity) {
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 批量删除APP任务记录
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if (isValid) {
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }
}
